home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / misc / sci / RARS_Amiga_2.lha / RARS / dynamic.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-31  |  5.5 KB  |  127 lines

  1. // DYNAMIC.CPP - "driver" function for RARS - M. Timin, Feb. 1995
  2. // This robot has no static or global variables,
  3. // so it can drive any number of cars.  
  4. // There is a static and a global associated with passing the name,
  5. // but the calling program expects that and handles it OK.
  6. // adapted to ver. 0.39 3/6/95 by M. Timin
  7.  
  8. // The language here can be considered to be ANSI C or C++.
  9.  
  10. #include <string.h>
  11. #include <stdlib.h>
  12. #include <math.h>
  13. #include "car.h"
  14.  
  15. // These parameters may be adjusted to get better performance:
  16. const double CORN_SPD_CON = 6.1;   // determines how fast to take corners
  17. const double STEER_GAIN = 2.5;     // servo gain, for staying in "lane"
  18. const double STEER_DAMP = 1.5;     // servo damping, to prevent "weaving"
  19. const double END_ACCEL = .27; // we accelerate until this fraction of length
  20. const double END_CORNER = 2.5;// used to decide when to start leaving the corer
  21. const double ESC_ALPHA = .03; // after a crash, set alpha like this, + or -
  22. const double SLIP_LIM = 4.5;  // maximum wheel slip, ft/sec, in wheel_slip()
  23. const double SLIP_CON = 70.0; // sets power & slip during linear acceleration
  24.  
  25. extern char* glob_name;       // The name string, below, will be copied here
  26.  
  27. // The following function calculates the speed for a corner.
  28. // The lateral force produced by cornering is proportional to the square
  29. // of the speed, and is inversely proportional to the radius of the path.
  30. // Therefore, the attainable cornering speed for differnt radii is
  31. // proportional to the square root of the radius.  This function implements
  32. // that rule.  The value to use for CORN_SPD_CON can be determined by
  33. // trial and error.  Example result: if the car is following a path with
  34. // radius of 100 ft, and if CORN_SPD_CON is 5.0, then crn_spd is 50 ft/sec.
  35. double crn_spd(double radius)
  36. {
  37.    if(radius < 0.0)         // change sign of negative radius
  38.       radius = -radius;
  39.    else if(radius == 0.0)   // This is just insurance, this funtion doesn't
  40.       return(200.0);        // make sense when the radius is zero.
  41.    return CORN_SPD_CON * sqrt(radius);
  42. }
  43.  
  44. // In order to set vc, if you know how fast you want to go (goal), and how
  45. // fast you are going now (present), This function will compute a reasonable
  46. // value for vc.  The value is never very far from the present speed, both
  47. // to attempt to stay within the power limit, and to maintain steering control.
  48. // You can adjust the resulting slip by changing SLIP_LIM.
  49. double wl_spd(double goal, double present)
  50. {
  51.    double ws;
  52.  
  53.    if(present > goal + 2 * SLIP_LIM)  // if too fast,
  54.       ws = present - SLIP_LIM;      // slow down.
  55.    else if(present < goal - 2 * SLIP_LIM)  // if too slow,
  56.       ws = present + SLIP_LIM;             // accelerate.
  57.    else                           // if quite close,
  58.       ws = (goal + present) / 2;      // approach desired speed gently.
  59.  
  60.    return ws;
  61. }
  62.  
  63. // The task of this function is to compute vc and alpha. 
  64. con_vec dynamic(situation s)
  65. {
  66.    const char name[] = "Dynamic";      // This is the robot driver's name!
  67.    static int init_flag = 1;          // cleared by first call
  68.    double speed;                      // target speed for cornering, ft/sec
  69.    double speed_next;                 // target speed for next corner
  70.    con_vec result;                    // This is what is returned.
  71.    double width;                      // track width, feet
  72.    double alpha, vc;           // components of result
  73.    double arg;                 // for temporary storage of calculation
  74.  
  75.    // This paragraph has nothing to do with car control; it is just
  76.    // to identify the driver by copying its name to a global RAM area:
  77.    // This happens only on the very first call to this function
  78.    if(init_flag)  {            // first time through, only copy name:
  79.       strcpy(glob_name, name);
  80.       init_flag = 0;
  81.       result.alpha = result.vc = 0;
  82.       return result;
  83.    }
  84.  
  85.    if(stuck(s.backward, s.v,s.vn, s.to_lft,s.to_rgt, &result.alpha,&result.vc))
  86.       return result;
  87.  
  88.    // Set alpha based on a servo-mechanism approach, trying to stay
  89.    // in the middle of the track, i.e., s.to_left equal to .5 * width:
  90.    width = s.to_lft + s.to_rgt;                        // find width of track
  91.    alpha = STEER_GAIN * (s.to_lft - .5 * width) / width;
  92.    alpha -= STEER_DAMP * s.vn / s.v;  // This is damping, to prevent oscillation
  93.  
  94.    // calculate target speeds for current corner and the next:
  95.    if(s.cur_rad == 0.0)
  96.       arg = 0.0;
  97.    else if(s.cur_rad > 0.0)
  98.       arg = s.cur_rad + .5 * width;
  99.    else
  100.       arg = s.cur_rad - .5 * width;
  101.    speed = crn_spd(arg);      // speed is based on radius
  102.  
  103.    if(s.nex_rad == 0.0)
  104.       arg = 0.0;
  105.    else if(s.nex_rad > 0.0)
  106.       arg = s.nex_rad + .5 * width;
  107.    else
  108.       arg = s.nex_rad - .5 * width;
  109.    speed_next = crn_spd(arg); // of center line of track.
  110.  
  111.    // now set the tire speed, vc:
  112.    if(s.cur_rad == 0.0)                  // If we are on a straightaway,
  113.       if(s.to_end > END_ACCEL * s.cur_len) // if we are far from the end,
  114.          vc = s.v + SLIP_CON / s.v;          // keep accellerating near full power
  115.       else                    // otherwise,
  116.          vc = wl_spd(speed_next, s.v);    // brake for next corner
  117.    else                              // If we're in the curve, maintain speed.
  118.       if(s.to_end * (s.cur_rad + .5 * width) > END_CORNER * width)
  119.                   // if we are far from the next corner, stay at "speed".
  120.          vc = wl_spd(speed, s.v);
  121.       else        // but when we near the next corner, adjust to "speed_next"
  122.          vc = wl_spd(speed_next, s.v);
  123.  
  124.    result.vc = vc;   result.alpha = alpha;
  125.    return result;
  126. }
  127.